package com.ada.sm2;

import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.util.encoders.Hex;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;

public class SM2PublicKeyApp {
    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());

        // Generate SM2 key pair
        AsymmetricCipherKeyPair keyPair = generateSM2KeyPair();

        ECPrivateKeyParameters privateKey = (ECPrivateKeyParameters) keyPair.getPrivate();
        ECPublicKeyParameters publicKey = (ECPublicKeyParameters) keyPair.getPublic();

        Long time=System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            extracted(publicKey, privateKey);
        }
        time=System.currentTimeMillis()-time;
        System.out.println(time);
    }

    private static void extracted(ECPublicKeyParameters publicKey, ECPrivateKeyParameters privateKey) throws Exception {
        String plainText = "Hello, SM2!";

        byte[] encryptedData = encryptWithPublicKey(plainText.getBytes(), publicKey);
        byte[] decryptedData = decryptWithPrivateKey(encryptedData, privateKey);

        //System.out.println("Original Text: " + plainText);
        //System.out.println("Encrypted Data: " + Hex.toHexString(encryptedData));
        //System.out.println("Decrypted Text: " + new String(decryptedData));
    }

    // Generate SM2 key pair
    public static AsymmetricCipherKeyPair generateSM2KeyPair() throws NoSuchAlgorithmException {
        ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("sm2p256v1");
        ECDomainParameters ecParams = new ECDomainParameters(
                ecSpec.getCurve(), ecSpec.getG(), ecSpec.getN(), ecSpec.getH());

        ECKeyGenerationParameters keyGenParams = new ECKeyGenerationParameters(ecParams, SecureRandom.getInstance("SHA1PRNG"));
        ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
        keyPairGenerator.init(keyGenParams);
        return keyPairGenerator.generateKeyPair();
    }

    // Encrypt using public key
    public static byte[] encryptWithPublicKey(byte[] data, ECPublicKeyParameters publicKey) throws Exception {
        SM2Engine engine = new SM2Engine();
        engine.init(true, new ParametersWithRandom(publicKey, new SecureRandom()));

        return engine.processBlock(data, 0, data.length);
    }

    // Decrypt using private key
    public static byte[] decryptWithPrivateKey(byte[] data, ECPrivateKeyParameters privateKey) throws Exception {
        SM2Engine engine = new SM2Engine();
        engine.init(false, privateKey);

        return engine.processBlock(data, 0, data.length);
    }
}
